﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using Shell.Structure;
using System.Xml.Linq;

namespace Shell
{
    public partial class MainForm : Form
    {
        private IntPtr _hWnd = IntPtr.Zero;
        private IntPtr _hdc = IntPtr.Zero;
        private Thread _thread;
        private bool _isRunning = false;
        private bool _isChecking = false;

        private Sequence _sequence;
        private List<Sequence> _allSequence;

        private EventWaitHandle _handle;

        public MainForm()
        {
            InitializeComponent();

            _allSequence = new List<Sequence>();
            string[] configFiles = System.IO.Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory + "configs", "*.xml");
            foreach (string configFile in configFiles)
            {
                Sequence s = GetSequence(configFile);
                _allSequence.Add(s);

                Button btn = new Button();
                btn.Width = 150;
                btn.Text = s.Caption;
                btn.Tag = s;
                btn.Click += new EventHandler(btn_Click);
                this.flowLayoutPanel1.Controls.Add(btn);
            }

            //_sequence = new Sequence();
            //_sequence = GetSequence();


            this.Shown += new EventHandler(Form1_Shown);

            this.Text = "version:" + this.GetType().Assembly.GetName().Version.ToString();
        }

        void btn_Click(object sender, EventArgs e)
        {
            _sequence = (sender as Button).Tag as Sequence;
            this.Text = _sequence.Caption;
        }

        private Sequence GetSequence(string path)
        {
            Sequence s = new Sequence();
            XDocument xDoc = XDocument.Load(path);

            s.Caption = xDoc.Root.Attribute("caption").Value;
            foreach (XElement xEl in xDoc.Root.Element("conditions").Elements("add"))
            {
                ConditionDef c = new ConditionDef(
                    xEl.Attribute("name").Value,
                    xEl.Attribute("pos").Value,
                    xEl.Attribute("rgb").Value);
                s.Condition.Add(c);
            }

            foreach (XElement xTrue in xDoc.Root.Element("enable").Elements("true"))
            {
                string name = xTrue.Attribute("name").Value;
                foreach (ConditionDef c in s.Condition)
                {
                    if (c.Name == name)
                    {
                        s.EnableCondition.Add(new Condition(true, c));
                        break;
                    }
                }
            }

            foreach (XElement xTrue in xDoc.Root.Element("enable").Elements("false"))
            {
                string name = xTrue.Attribute("name").Value;
                foreach (ConditionDef c in s.Condition)
                {
                    if (c.Name == name)
                    {
                        s.EnableCondition.Add(new Condition(false, c));
                        break;
                    }
                }
            }

            s.NonGcdSequence = GetNonGCDSubSequence(s, xDoc.Root.Element("casts-non-gcd"));
            s.GcdSequence = GetSubSequence(s, xDoc.Root.Element("casts-gcd"));

            return s;
        }

        private NonGCDSubSequence GetNonGCDSubSequence(Sequence s, XElement xEl)
        {
            NonGCDSubSequence sequence = new NonGCDSubSequence();

            if (xEl.Element("enable") != null)
            {
                foreach (XElement xTrue in xEl.Element("enable").Elements("true"))
                {
                    string name = xTrue.Attribute("name").Value;
                    foreach (ConditionDef c in s.Condition)
                    {
                        if (c.Name == name)
                        {
                            sequence.EnableCondition.Add(new Condition(true, c));
                            break;
                        }
                    }
                }

                foreach (XElement xTrue in xEl.Element("enable").Elements("false"))
                {
                    string name = xTrue.Attribute("name").Value;
                    foreach (ConditionDef c in s.Condition)
                    {
                        if (c.Name == name)
                        {
                            sequence.EnableCondition.Add(new Condition(false, c));
                            break;
                        }
                    }
                }
            }

            foreach (XElement xSub in xEl.Elements("sub-sequence"))
            {
                sequence.SubSequences.Add(GetNonGCDSubSequence(s, xSub));
            }

            if (sequence.SubSequences.Count == 0)
            {
                foreach (XElement xCast in xEl.Elements("cast"))
                {
                    Cast ct = new Cast(xCast.Attribute("key").Value);

                    foreach (XElement xTrue in xCast.Elements("true"))
                    {
                        string name = xTrue.Attribute("name").Value;
                        foreach (ConditionDef c in s.Condition)
                        {
                            if (c.Name == name)
                            {
                                ct.Conditions.Add(new Condition(true, c));
                                break;
                            }
                        }
                    }

                    foreach (XElement xFalse in xCast.Elements("false"))
                    {
                        string name = xFalse.Attribute("name").Value;
                        foreach (ConditionDef c in s.Condition)
                        {
                            if (c.Name == name)
                            {
                                ct.Conditions.Add(new Condition(false, c));
                                break;
                            }
                        }
                    }
                    sequence.Casts.Add(ct);
                }
            }
            return sequence;
        }

        private GCDSubSequence GetSubSequence(Sequence s, XElement xEl)
        {
            GCDSubSequence sequence = new GCDSubSequence();

            if (xEl.Element("enable") != null)
            {
                foreach (XElement xTrue in xEl.Element("enable").Elements("true"))
                {
                    string name = xTrue.Attribute("name").Value;
                    foreach (ConditionDef c in s.Condition)
                    {
                        if (c.Name == name)
                        {
                            sequence.EnableCondition.Add(new Condition(true, c));
                            break;
                        }
                    }
                }

                foreach (XElement xTrue in xEl.Element("enable").Elements("false"))
                {
                    string name = xTrue.Attribute("name").Value;
                    foreach (ConditionDef c in s.Condition)
                    {
                        if (c.Name == name)
                        {
                            sequence.EnableCondition.Add(new Condition(false, c));
                            break;
                        }
                    }
                }
            }

            foreach (XElement xSub in xEl.Elements("sub-sequence"))
            {
                sequence.SubSequences.Add(GetSubSequence(s, xSub));
            }

            if (sequence.SubSequences.Count == 0)
            {
                foreach (XElement xCast in xEl.Elements("cast"))
                {
                    Cast ct = new Cast(xCast.Attribute("key").Value);

                    foreach (XElement xTrue in xCast.Elements("true"))
                    {
                        string name = xTrue.Attribute("name").Value;
                        foreach (ConditionDef c in s.Condition)
                        {
                            if (c.Name == name)
                            {
                                ct.Conditions.Add(new Condition(true, c));
                                break;
                            }
                        }
                    }

                    foreach (XElement xFalse in xCast.Elements("false"))
                    {
                        string name = xFalse.Attribute("name").Value;
                        foreach (ConditionDef c in s.Condition)
                        {
                            if (c.Name == name)
                            {
                                ct.Conditions.Add(new Condition(false, c));
                                break;
                            }
                        }
                    }
                    sequence.Casts.Add(ct);
                }
            }
            return sequence;
        }

        void Form1_Shown(object sender, EventArgs e)
        {
            _btnAttach_Click(null, null);
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            _isChecking = false;
            _isRunning = false;

            if (_hWnd != null)
            {
                APIUtil.ReleaseDC(_hWnd, _hdc);
            }

            if (_handle != null)
            {
                _handle.WaitOne();
            }

            base.OnClosing(e);
        }

        private void _btnAttach_Click(object sender, EventArgs e)
        {
            _hWnd = APIUtil.FindWindow(null, "魔兽世界");
            if (_hWnd == IntPtr.Zero)
            {
                _hdc = IntPtr.Zero;

                MessageBox.Show("没有发现客户端!");
                _btnStart.Enabled = false;
                _btnStop.Enabled = false;
            }
            else
            {
                _hdc = APIUtil.GetDC(_hWnd);

                _btnStart.Enabled = true;
                _btnStop.Enabled = false;

                if (_thread == null)
                {
                    _handle = new EventWaitHandle(false, EventResetMode.ManualReset);
                    _thread = new Thread(Running);
                    _isRunning = true;
                    _thread.Start();
                }
            }
        }

        private void _btnStart_Click(object sender, EventArgs e)
        {
            _isChecking = true;
            _btnStart.Enabled = false;
            _btnStop.Enabled = true;
        }

        private void _btnStop_Click(object sender, EventArgs e)
        {
            _isChecking = false;
            _btnStart.Enabled = true;
            _btnStop.Enabled = false;
        }

        private void Running()
        {
            while (_isRunning)
            {
                if (_hWnd == IntPtr.Zero)
                {
                    Thread.Sleep(1000);
                    continue;
                }
                else if (_isChecking && _sequence != null)
                {
                    //Console.WriteLine(".isRunning-------->");
                    // 检查条件的情况
                    for (int cIndex = 0; cIndex < _sequence.Condition.Count; cIndex++)
                    {
                        uint pixel = APIUtil.GetPixel(_hdc, _sequence.Condition[cIndex].Pos.X, _sequence.Condition[cIndex].Pos.Y);

                        //Console.WriteLine(string.Format(".isRunning-getpixel------->{0}",pixel));
                        if (_sequence.Condition[cIndex].RGB == pixel)
                        {

                            //Console.WriteLine(_sequence.Condition[cIndex].Name+".ispassed");
                            _sequence.Condition[cIndex].IsPassed = true;
                        }
                        else
                        {
                            _sequence.Condition[cIndex].IsPassed = false;
                        }
                    }

                    if (_sequence.IsPassed())
                    {
                        // 判断没有GCD的技能
                        if (_sequence.NonGcdSequence.IsPassed())
                        {
                            _sequence.NonGcdSequence.Execute(this._hWnd);
                        }

                        // 判断有GCD的技能
                        if (_sequence.GcdSequence.IsPassed())
                        {
                            _sequence.GcdSequence.Execute(this._hWnd);
                        }
                    }
                    Thread.Sleep(20);
                }
            }
            _handle.Set();
        }

        private void PressKey(int key)
        {
            APIUtil.PostMessage(this._hWnd, WndMessage.WM_KEYDOWN, (uint)key, (uint)0);
            Thread.Sleep(20);
            APIUtil.PostMessage(this._hWnd, WndMessage.WM_KEYUP, (uint)key, (uint)0);
        }

        private void m_btnBrowse_Click(object sender, EventArgs e)
        {
            SelectTargetWindow window = new SelectTargetWindow();
            window.ShowDialog();
        }

        private void _btnExit_Click(object sender, EventArgs e)
        {
            Close();
        }
    }
}
